/**
 * Friendly Interactive Recursion Educator (FIRE)
 * COMS 4115: Programming Languages & Translators
 * Prof. Aho
 * 
 * @author Brian Lu
 * @author Sahar Hasan
 * @author Steve Hehl
 * @author Tristan Naumann
 * @version 2009-05-12
 */
package fire;

import java.util.*;

/**
 * Stores the variables in the current scope and supports nested scope by
 * checking this scope for a variable and then recursively checking parents. 
 */
public class Scope {
    Scope parent = null;
    Map<String,Symbol> symbols = new HashMap<String, Symbol>(); // symbols in scope

    /**
     * Creates a new scope nested in the parent scope. First scope should be
     * created with a null parent.
     * @param parent the parent scope
     */
    public Scope(Scope parent) {
        this.parent = parent;
    }

    public Scope pop() { return parent; } // aka getParent()

    /**
     * Get the list of variable names in the current scope
     * @return list of variables names in current scope
     */
    public ArrayList<String> getScopeVariables(){
    	Set<String> keys = symbols.keySet(); 
    	ArrayList<String> vars = new ArrayList<String>();
    	Iterator<String> itr = keys.iterator();
    	while(itr.hasNext()){
    		String name = itr.next(); 
    		Symbol s = symbols.get(name);
    		if(s instanceof VariableSymbol){
    			// adds prefix fire_ for security concerns
    			vars.add("fire_"+name);		
    		}
    	}
    	
    	return vars;	
    }
    
    /**
     * Defines a new variable with given name and type in this scope
     * @param name the variable name
     * @param type the variable type
     * @return the VariableSymbol for the name and type
     */
    public Symbol defineVariable(String name, Symbol type) {
        Symbol s = new VariableSymbol(name,type);
        symbols.put(name, s);
        return s;
    }

    /**
     * Defines a new function with the given name and return type.
     * NOTE: must add arguments to the function symbol afterward.
     * @param name the name of the function
     * @param returnType the return type of the function
     * @param recursive is this the primary recursive function?
     * @return the FunctionSymbol for this type
     */
    public Symbol defineFunction(String name, Symbol returnType, boolean recursive) {
        Symbol s = new FunctionSymbol(name,returnType, recursive);
        symbols.put(name, s);
        return s;
    }
    
    // Same as above, assumes this is not the recursive function.
    public Symbol defineFunction(String name, Symbol returnType) {
        Symbol s = new FunctionSymbol(name,returnType, false);
        symbols.put(name, s);
        return s;
    }

    /**
     * Try to look up variable with given name.
     * @param name the variable name
     * @return the variable symbol or null if it could not be found.
     */
    public Symbol lookup(String name) {
        Symbol s = symbols.get(name);
        if ( s!=null ) {
            return s;  // found it
        }
        // if not, then check enclosing scope
        if ( parent!=null ) {
            return parent.lookup(name);
        }
        return null; // couldn't find it
    }
}
